package com.zhentao.config;

import cn.hutool.json.JSONUtil;
import com.zhentao.Jwtfilter.JwtFilter;
import com.zhentao.constants.Constants;
import com.zhentao.pojo.TUser;
import com.zhentao.redis.RedisCacheUtil;
import com.zhentao.result.Result;
import com.zhentao.utils.JwtService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfig {
    @Resource
    private RedisCacheUtil redisCacheUtil;

    @Resource
    private DyConfig dyConfig;

    @Resource
    private JwtFilter jwtFilter;
    @Resource
    private JwtService jwtService;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests().antMatchers("/doc.html").permitAll();
        //登录
        http.formLogin(config-> {
            config.loginProcessingUrl("/user/login").successHandler((request, response, authentication) -> {
                        TUser user = (TUser) authentication.getPrincipal();
                        if (user==null){
                            response.getWriter().println(JSONUtil.toJsonStr(Result.ERROR("账号不存在")));
                            return;
                        }
                        Map<String,Object> map = new HashMap<>();
                        user.setPassword("");
                        map.put("user",user);
                        String tokenKey = "user_session:" + user.getUserId(); // Redis中的键名

                        // 检查Redis中是否已存在该用户的会话
                        String existingToken = redisCacheUtil.getCacheObject(tokenKey);
                        if (existingToken != null) {
                            // 决策：可以选择更新旧令牌、记录日志、发送通知或拒绝登录
                            // 这里简单演示拒绝登录
                            response.getWriter().println(JSONUtil.toJsonStr(Result.ERROR("该账号已在其他设备登录")));
                            return;
                        }
                        if (user.getState()==1){
                            response.getWriter().println(JSONUtil.toJsonStr(Result.ERROR("该账号已禁用")));
                        }else {
                            String token = JwtService.createToken(map);
                            redisCacheUtil.setCacheObject(token, user, Constants.EXPIRE_TIME, TimeUnit.SECONDS);
                            String rememberMe = request.getParameter("rememberMe");
                            if (Boolean.parseBoolean(rememberMe)){
                                //存7天
                                log.info("存7天============>");
                                jwtService.refreshToken(user, Constants.EXPIRE_TIME, TimeUnit.SECONDS);
                            }else {
                                //存30天
                                log.info("存30分钟============>");
                                jwtService.refreshToken(user, Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
                            }
//                            先进行存储30分钟
                            redisCacheUtil.setCacheObject(tokenKey,"0",Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);


                            response.setCharacterEncoding("UTF-8");
                            response.getWriter().println(JSONUtil.toJsonStr(Result.OK(token)));
                        }
            })
                    .failureHandler((request, response, exception) -> {
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().println(JSONUtil.toJsonStr(Result.PASSWORD_ERROR()));
                    });
        });
        // 登出配置
        http.logout(config -> {
            config.logoutUrl("/logout")
                    .logoutSuccessHandler((request, response, authentication) -> {
                        response.setCharacterEncoding("UTF-8");
                        // 获取请求头token
                        String token = request.getHeader(Constants.TOKEN);
                        if (token != null) {
                            Map<String, Object> map = JwtService.getClaimsMap(token);
                            redisCacheUtil.redisTemplate.delete("user_session:"+map.toString().split("userId=")[1].split(",")[0]);
                            redisCacheUtil.redisTemplate.delete(token);
                        } else {
                            log.warn("无法获取请求头中的Token信息");
                        }
                        // 添加详细日志输出
                        if (authentication != null && authentication.getPrincipal() instanceof TUser) {
                            System.out.println("正在退出登录");
                            TUser user = (TUser) authentication.getPrincipal();
                            log.info("用户 {} 正在退出", user.getUsername());
                            jwtService.removeToken(user);
                        } else {
                            log.warn("无法获取认证信息中的用户主体");
                        }
                        // 返回JSON格式的响应
                        response.getWriter().println(JSONUtil.toJsonStr(Result.LOGIN_OUT()));
                    });
        });
        //异常
        http.exceptionHandling(config-> {
            config.authenticationEntryPoint((request, response, authException) -> {
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().println(JSONUtil.toJsonStr(Result.ERROR("身份认证失败")));
                    })
                    .accessDeniedHandler((request, response, accessDeniedException) -> {
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().println(JSONUtil.toJsonStr(Result.ERROR("没有权限")));
                    });
        });
        //拦截权限
        http.authorizeHttpRequests(config-> {
            config.antMatchers("/user/login","/user/logout").permitAll().anyRequest().access(dyConfig);
        });
        //防止csrf
        http.csrf(config-> {
            config.disable();
        });
        //关闭session
        http.sessionManagement(config-> {
            config.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        });
        //过滤器
        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}